﻿using Gym.Domain.Common;
using Gym.Infrastructure.Persistence;
using MediatR;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Gym.Infrastructure.Middleware
{
    public class EventualConsistencyMiddleware
    {
        public const string DomainEventsKey = "DomainEventsKey";
        private readonly RequestDelegate _next;

        public EventualConsistencyMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context, IPublisher publisher, GymDbContext dbContext)
        { 
            var transaction = await dbContext.Database.BeginTransactionAsync();
            context.Response.OnCompleted(async ()=>
            {
                try
                {
                    if(context.Items.TryGetValue(DomainEventsKey, out var value) &&
                    value is Queue<IDomainEvent> domainEvents)
                    {
                        while(domainEvents.TryDequeue(out var domainEvent))
                        {
                            await publisher.Publish(domainEvent);
                        }

                        await transaction.CommitAsync();
                    }
                }
                finally
                {
                    await transaction.DisposeAsync();
                }
            });

            await _next(context);
        }
    }
}
